var fs = require('fs');
var path = require('path');
var utils = require('../util/utils');
var Loader = require('pomelo-loader');
var pathUtil = require('../util/pathUtil');
var crypto = require('crypto');

module.exports = function(app, opts) {
  return new Component(app, opts);
};
//字典压缩组件
var Component = function(app, opts) {
  this.app = app;//上下文
  this.dict = {};//字典
  this.abbrs = {};//路由缩写
  this.userDicPath = null;//用户字典路径
  this.version = "";//版本

  //Set user dictionary
  var p = path.join(app.getBase(), '/config/dictionary.json');//默认的字典配置文件路径
  if(!!opts && !!opts.dict) {//如果在配置中设置了字典的路径
    p = opts.dict;//更换了配置中的字典的路径
  }
  if(fs.existsSync(p)) {//判断路径中的文件是否存在
    this.userDicPath = p;//保存该路径
  }
};

var pro = Component.prototype;

pro.name = '__dictionary__';

pro.start = function(cb) {//组件启动函数
  var servers = this.app.get('servers');//获取所有服务器信息
  var routes = [];

  //Load all the handler files
  for(var serverType in servers) {//遍历所有服务器 根据类型
    var p = pathUtil.getHandlerPath(this.app.getBase(), serverType);//获取某服务器类型的handler目录
    if(!p) {//如果是空的
      continue;//处理其他类型服务器
    }

    var handlers = Loader.load(p, this.app);//加载handler目录下的所有JS模块

    for(var name in handlers) {//遍历名字
      var handler = handlers[name];//取出对应的模块
      for(var key in handler) {//遍历模块内的属性
        if(typeof(handler[key]) === 'function') {//如该该属性是个函数
          routes.push(serverType + '.' + name + '.' + key);//保存该路由信息，格式为服务器类型.模块名字.函数名字
        }
      }
    }
  }

  //Sort the route to make sure all the routers abbr are the same in all the servers
  //排序路由以确保所有的路由缩写在所有服务器中都是相同的
  routes.sort();
  var abbr;
  var i;
  for(i = 0; i < routes.length; i++) {//遍历所有路由
    abbr = i + 1;//路由缩写从1开始
    this.abbrs[abbr] = routes[i];//路由缩写->路由信息 映射
    this.dict[routes[i]] = abbr;//路由信息->路由缩写 映射
  }

  //Load user dictionary
  if(!!this.userDicPath) {//如果存在用户字典 客户端路由字典
    var userDic = require(this.userDicPath);//加载字典

    abbr = routes.length + 1;//客户端路由字典起始值为服务器路由字典长度+1
    for(i = 0; i < userDic.length; i++) {//遍历客户端路由字典
      var route = userDic[i];//路由信息

      this.abbrs[abbr] = route;//路由缩写->路由信息 映射
      this.dict[route] = abbr;//路由信息->路由缩写 映射
      abbr++;//增加路由缩写值
    }
  }
  
  this.version = crypto.createHash('md5').update(JSON.stringify(this.dict)).digest('base64');
  //版本号算法：先使用内建crypto模块创建一个md5的hash object，该对象用于产生HASH摘要
  //调用hash object的update方法，将数据写入，传入的是JSON字符串，编码格式是二进制
  //最后调用hash object的digest方法，产生HASH摘要，指定编码格式为base64，如果不指定，将返回一块缓冲区


  utils.invokeCallback(cb);//done()继续处理下一个组件
};

pro.getDict = function() {//获取路由信息->路由缩写字典
  return this.dict;
};

pro.getAbbrs = function() {//获取路由缩写->路由信息字典
  return this.abbrs;
};

pro.getVersion = function() {//获取版本号
  return this.version;
};
